<?php

namespace xyb2b;

use GuzzleHttp\Client;
use think\helper\Str;

class Request
{
    protected $apiUrl = 'http://bbcapi.test.xyb2b.com/open/api/route'; // API接口地址
//    protected $apiUrl = 'http://cigi.com:8000/api/news/abced'; // API接口地址
    protected $type = 'POST'; // 请求方式
    protected $content = []; // 请求数据
    protected $options = []; // 请求配置
    protected $msgType = ''; // 操作码
    protected $response_headers = ''; // 响应头
    protected $merchantId = '2024112997124650'; // 商户ID
    protected $merchantKey = '1IDQP4SDR0009407300A0000723E2782'; // 商户密钥
    protected $version = '2'; // 版本
    protected $signType = 'MD5'; // 签名类型
    protected $businessId; // 业务消息ID
    protected $headers = [];

    public function __construct()
    {
        //判断是否是开发环境
        if ('prod' == env('APP_ENV')) {
            $this->apiUrl = 'http://api.bbc.xyb2b.com/open/api/route';
            $this->merchantId = '2024122552379486';
            $this->merchantKey = '1IFTKENE201H440DA8C00000F2CDCA60';
        }
    }

    // 过滤不参与签名的字段（空值，sign，sign_type）
    protected function paraFilter($sArray)
    {
        $result = [];
        if ($sArray === null || count($sArray) === 0) {
            return $result;
        }
        foreach ($sArray as $key => $value) {
            // 签名与签名类型不参与签名，且过滤掉空值
            if ($value == "" || strcasecmp($key, 'sign') === 0 || strcasecmp($key, 'sign_type') === 0) {
                continue;
            }
            $result[$key] = $value;
        }

        return $result;
    }

    // 生成签名字符串
    protected function createLinkString($params)
    {
        $keys = array_keys($params);
        uksort($keys, function ($a, $b) {
            return strnatcmp($a, $b);
        });

        $prestr = '';
        foreach ($keys as $i => $key) {
            $val = $params[$key];
            if(is_array($val)){
                $prestr .= $key . "=" . json_encode($val,JSON_UNESCAPED_UNICODE) . "&";
            }else {
                $prestr .= $key . "=" . $val . "&";
            }
        }
        $prestr = rtrim($prestr,'&');

        return $prestr;
    }

    // 构建签名
    protected function buildRequestSign($sPara, $key, $charset = 'UTF-8', $signType = 'MD5')
    {
        $prestr = $this->createLinkString($sPara);

        if ($signType === 'MD5') {
            $prestr .= $key; // 在拼接完所有参数后，加入密钥

            if ($charset === 'UTF-8') {
                return hash('md5', $prestr);
            } else {
                $prestr = iconv($charset, 'UTF-8', $prestr);
                return hash('md5', $prestr);
            }
        }
    }

    // 获取签名
    protected function buildSign($params, $key)
    {
        // 去除不需要参与签名的字段
        $filterParams = $this->paraFilter($params);

        file_put_contents("debug_log.txt", "去除不签名字段: " . json_encode($filterParams , true) . PHP_EOL, FILE_APPEND);

        return $this->buildRequestSign($filterParams, $key, 'UTF-8', 'MD5');
    }

    function getSign($strParam, $appKey)
    {
        // 使用json_decode解析JSON字符串为关联数组（假设传入的JSON格式是正确的），第二个参数true表示解析为关联数组
//        $dataMap = json_decode($strParam, true);
        $dataMap = $strParam;
        // 对解析后的数组按照字段名进行排序，模拟Feature.OrderedField效果
        uksort($dataMap, function ($a, $b) {
            return strnatcmp($a, $b);
        });
        return $this->buildSign($dataMap, $appKey);
    }

    // 设置请求头
    protected function headers()
    {
        $this->headers = [
            'Content-Type' => 'application/json',
        ];
    }

    // 设置请求配置
    protected function options()
    {
        $this->options['headers'] = $this->headers;
        $this->options['timeout'] = $this->options['timeout'] ?? 60;
    }

    // 设置身份验证
    protected function auth()
    {
        $this->headers();
        $this->options();
    }

    // 发送请求
    protected function send()
    {
        $client = new Client();
        $url = $this->apiUrl;

        $this->content['biz_content'] = stripslashes(json_encode($this->content['biz_content'] , JSON_UNESCAPED_UNICODE));

        if ($this->type == 'GET') {
            $url .= '?' . http_build_query($this->content);
        } else {
            $this->options['body'] = json_encode($this->content, JSON_UNESCAPED_UNICODE);
        }

        // 发送请求
        $response = $client->request($this->type, $url, $this->options);
        $this->response_headers = $response->getHeaders();
        return $response->getBody()->getContents();
    }

    // 返回固定的 business_id
    protected function generateBusinessId()
    {
        return Str::random(30); // 返回固定的 business_id
    }

    // 执行请求
    public function exec()
    {
        $this->auth();

        // 设置请求的固定字段
        $this->content['merchant_id'] = $this->merchantId;
        $this->content['version'] = $this->version;
        $this->content['sign_type'] = $this->signType;

        // 自动生成固定的 business_id
        $this->businessId = $this->generateBusinessId();
        $this->content['business_id'] = $this->businessId;

        // 设置操作码
        $this->content['opcode'] = $this->msgType; // 自动填充操作码

        // 生成签名
        $this->content['sign'] = $this->getSign($this->content, $this->merchantKey);

        // 发送请求并获取响应
        $response = $this->send();

        //var_dump($response);

        // 解析返回的 JSON 数据
        $responseArray = json_decode($response, true);

        //var_dump($responseArray);

        // 检查返回结果的 ret_code
        if (isset($responseArray['ret_code']) && $responseArray['ret_code'] == 200) {
            // 返回正常数据时解析 result_content
            if (isset($responseArray['result_content'])) {
                return json_decode($responseArray['result_content'], true);
            } else {
                throw new \Exception("请求成功，但缺少 result_content 字段");
            }
        } else {
            // 如果 ret_code 不是 200，抛出异常或返回错误信息
            throw new \Exception("请求失败，错误信息：" . ($responseArray['ret_msg'] ?? '未知错误'), $responseArray['ret_code'] ?? 0);
        }
    }
}
